package com.genius.util.Utils.BeanUtils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

public class BeanLab {
    private final static String GET = "get";
    private final static String SET = "set";
    public static  <T,E> T  switchSoul(E source, Class<T> tClazz, String... ignoreProperties){
        T target = null;
        try {
            target = tClazz.getConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }
        HashMap<String, Integer> propMap = new HashMap<>();
        for (String ignoreProperty : ignoreProperties) {
            propMap.put(ignoreProperty,0);
        }
        switchSoul(source,target,propMap);
        return target;
    }

    public static  <T,E> T  switchSoul(E source, T target, Map propMap){
        DecomposeStation targetStation = new DecomposeStation(target.getClass());
        DecomposeStation sourceStation = new DecomposeStation(source.getClass());
        Field[] targetFiled = targetStation.getHeartField();
        List<Field> fieldList = Arrays.stream(targetFiled).filter(data -> !propMap.containsKey(data)).collect(Collectors.toList());
        for (Field field : fieldList) {
            String methodName = getMethodGetOrSetName(field.getName());
            try {
                Method set = targetStation.getMethod(SET+methodName,field.getType());
                Method get = sourceStation.getMethod(GET+methodName);
                set.invoke(target,get.invoke(source));
            }catch (IllegalAccessException | InvocationTargetException e){
                continue;
            }
        }
        return target;
    }

    public static <E> Map<String, Object> twoWayFoil(E source){
        Map<String, Object> map = new HashMap<>();
        if(source==null){
            return map;
        }
        DecomposeStation decomposeStation = new DecomposeStation(source.getClass());
        Field[] heartField = decomposeStation.getHeartField();
        for (Field field : heartField) {
            Object value = null;
            try {
                Method get = decomposeStation.getMethod(GET+getMethodGetOrSetName(field.getName()));
                value = get.invoke(source);
            }catch (IllegalAccessException | InvocationTargetException e){
            }
            map.put(field.getName(),value);
        }
        return map;
    }

    public static  <T> String beanToJson(T bean){
        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.writeValueAsString(bean);
        }catch (JsonProcessingException e){
            e.printStackTrace();
        }
       return null;
    }

    public static  <T> T jsonToBean(Class<T> tClazz,String json) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(json, tClazz);
    }

    public static  <T> List<T> jsonToArray(Class<T> tClazz,String json) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(json,mapper.getTypeFactory().constructParametricType(ArrayList.class,tClazz));
    }

    public static <T> T mapToBean(Class<T> tClazz,Map map){
        ObjectMapper mapper = new ObjectMapper();
        return mapper.convertValue(map,tClazz);
    }

    private static String getMethodGetOrSetName(String methodName){
        char firstChar = methodName.charAt(0);
        if(firstChar<=0x7a&&firstChar>=0x61){
            methodName = methodName.substring(0,1).toUpperCase()+methodName.substring(1);
        }
        return methodName;
    }
}
